Repository navigation
[APPS-2947] Add: return connection IDs from debugBundle and attach the bundle to framed backend calls - #566
Merged
gh-worker-dd-mergequeue-cf854d[bot] merged 2 commits intoOct 26, 2026
Conversation
🎉 All green!🧪 All tests passed 🔗 Commit SHA: 477b4b9 | Docs | View more details | Give us feedback! |
tyffical
force-pushed
the
tiffany.trinh/apps-2947-debug-bundle-connection-ids
branch
from
October 14, 2026 21:45
5126f2b to
5c7bf06
Compare
tyffical
marked this pull request as ready for review
October 16, 2026 01:06
tyffical
requested review from
Chau-DDOG,
duncanista,
oliverli and
sdkennedy2
and removed request for
a team
October 16, 2026 01:06
tyffical
force-pushed
the
tiffany.trinh/apps-2947-debug-bundle-connection-ids
branch
from
October 16, 2026 02:08
5c7bf06 to
43bb75f
Compare
oliverli
approved these changes
Oct 16, 2026
oliverli
left a comment
Collaborator
There was a problem hiding this comment.
The implementation looks correct. I found no correctness or security problems. The inline comments are about test coverage only, and they do not block this PR.
tyffical
force-pushed
the
tiffany.trinh/apps-2947-debug-bundle-connection-ids
branch
from
October 21, 2026 04:05
4a5e676 to
5f22e12
Compare
This was referenced Oct 21, 2026
tyffical
force-pushed
the
tiffany.trinh/apps-2947-debug-bundle-connection-ids
branch
2 times, most recently
from
October 23, 2026 14:52
2e8c7d4 to
cac186d
Compare
oliverli
approved these changes
Oct 26, 2026
tyffical
force-pushed
the
tiffany.trinh/apps-2947-debug-bundle-connection-ids
branch
3 times, most recently
from
October 26, 2026 20:50
9dbcd7f to
d51394c
Compare
POST /__dd/debugBundle answers with { code, allowedConnectionIds } when
the Accept header lists application/json without q=0, and keeps the
plain-text bundle otherwise. The route path and response type live in
the shared backend protocol so the browser client can use them.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
A dev client, built as apps-dev-client, installs a hook the postMessage
transport calls before each run-query. When the page is framed by a
Datadog page, found through ancestorOrigins or, on Firefox, from the
origin of the parent's answer to a ping, the hook fetches the function's
bundle from /__dd/debugBundle and returns it with the parent's exact
origin. A hook that fails, throws or stalls never stops the call. A
parent with an opaque ("null") origin gets the call without a bundle,
and the page warns once.
The Vite plugin prepends a module script for virtual:dd-apps-dev-client
to served HTML, ahead of Vite's base rewrite, and loads the built
apps-dev-client file for it. The virtual id resolves only for client
requests while the dev server runs.
The transport posts a bundle only to an exact origin and accepts a
run-query response only from window.parent and, when it posted to an
exact origin, only from that origin. It copies the bundle's
allowedConnectionIds by index into a plain array before checking them,
so an array subclass can't choose what gets posted through
Symbol.species.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
tyffical
force-pushed
the
tiffany.trinh/apps-2947-debug-bundle-connection-ids
branch
from
October 26, 2026 21:16
d51394c to
477b4b9
Compare
Contributor
Author
|
/merge |
|
View all feedbacks in Devflow UI.
The expected merge time in
|
gh-worker-dd-mergequeue-cf854d
Bot
merged commit Oct 26, 2026
3cb1023
into
master
15 of 17 checks passed
gh-worker-dd-mergequeue-cf854d
Bot
deleted the
tiffany.trinh/apps-2947-debug-bundle-connection-ids
branch
October 26, 2026 22:04
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Motivation
preview-asyncas the viewer, and its connection checks and consent prompt need that function's allowed connection IDs./__dd/debugBundle, then drops them; the endpoint returns only plain-text code.Architecture
flowchart LR subgraph frame["Preview frame (dev-served page)"] T["postMessageTransport"] DC["apps-dev-client hook (dev pages only)"] end DS["Dev server: POST /__dd/debugBundle"] P["Parent: Live Preview pane"] T -- "hook installed? await it, max 120s" --> DC DC -- "Accept: application/json (else plain text, as before)" --> DS DS -- "code + allowedConnectionIds" --> DC DC -- "targetOrigin + bundle" --> T T -- "run-query + bundle, exact https Datadog origin only" --> P P -- "run-query:response, from window.parent only" --> Tlocation.ancestorOrigins[0], or in Firefox the origin ofwindow.parent's answer to a ping. Any hook, ping or fetch failure posts the call without a bundle, so deployed apps, which have no hook, post to'*'as before.Changes
11 changes across the protocol, dev server, Vite plugin, dev client, transport and tests
DebugBundleResponse,DEBUG_BUNDLE_PATH, the message-type constants and the dev-client hook typespackages/plugins/apps/src/backend/protocol.ts{ code, allowedConnectionIds }as JSON whenAcceptlistsapplication/json; plain text otherwisepackages/plugins/apps/src/vite/dev-server.tsvirtual:dd-apps-dev-clientonly while a dev server runs, and link it from dev-served HTMLpackages/plugins/apps/src/vite/index.tsapps-dev-clientsub-build and its entrypackages/plugins/apps/package.json,packages/plugins/apps/src/built/apps-dev-client.tspackages/plugins/apps/src/backend/client/dev-client/dev-client.tspackages/plugins/apps/src/backend/client/transports/post-message-transport/post-message-transport.ts,types.tspackages/plugins/apps/src/backend/client/guards.ts,packages/plugins/apps/src/backend/client/request-id.tsdev-client.test.ts,post-message-transport.test.tsbasepackages/plugins/apps/src/vite/index.test.ts,dev-server.test.ts,dev-server.integration.test.ts,dev-client-build.test.tspackages/tests/src/_jest/helpers/fakeWindow.tspackages/plugins/apps/src/backend/client/execute-backend-function.test.tsQA Instructions
477b4b9e, and in staging on3.3.3-dev.1, a dev publish of that head. Setup: Local QA without npm link in the testing and QA guide, with the harness below./__dd/debugBundle{code, allowedConnectionIds}JSON withAccept: application/json; master's 415/403 request checks unchangedallowedConnectionIds ["conn-1"], from http and https framesapps-runtime.mjs3267 bytes;apps-dev-client.mjs3185 bytes, dev pages only3.3.3-dev.1, the demo app's framed call ran: itsgithub.pulls.listaction was accepted for high-code 5s after Vite restarted on the new versionDev server checks (curl)
qa-server.cjsandqa-server-base.cjsbelow, with theactionCatalogCall.backend.tsfixture under the app root and no auth.Browser checks (Playwright, Chromium and Firefox)
QA_BROWSER=chromiumorQA_BROWSER=firefox. Playwright fulfills the parent page locally, so no request reaches the named host; the page answersapp-builder:pingas App Builder's bridge does.Live Preview in staging (steps)
3.3.3-dev.1).@datadog/vite-pluginto it, reinstall, and fully restart Vite./@id/virtual:dd-apps-dev-clientis served and the*.backend.tsfiles load as proxy stubs.run-querycarriesbundle.allowedConnectionIds, and thepreview-asyncrun succeeds as the viewer (staging audit events).@datadog/create-appsapp; the staging run covers the same path.Captured dev server, browser and build output
QA harness source (dev servers, app and parent pages, browser and build scripts)
qa-app/holdsindex.html,nested/index.html(a copy),main.js,multi.html,multi.js,parent.html,parent-ping.html,backend/actionCatalogCall.backend.tsandnode_modules/@datadog/action-catalog(both copied withcp -RLfrompackages/tests/src/_jest/fixtures/apps_backend_project).Wis this repo's checkout andSthe harness directory, both passed as environment variables;QA_BROWSERpickschromium(default) orfirefox.Blast Radius
run-queryto'*', but replies not fromwindow.parentare ignored and malformed ones reject instead of hanging; App Builder replies from the parent./__dd/debugBundlereturns JSON only forAccept: application/json, Axios's default (no Axios caller found), and framed dev calls wait up to 60s for their function's build.Out of Scope / Follow-ups
13 items deferred
bundleas untrusted app input: any script in the frame can post arbitrarycodeandallowedConnectionIdsallow-same-origingrant, and areferrerpolicythat masksancestorOrigins[0]as"null"would skip the bundle, since that case doesn't fall back to a pingsandboxorreferrerpolicychangeswwwanddocs) are accepted as the parent, to keep custom org subdomains workingOriginto matchHost, so a preview edge that rewritesHostgets 403 and the pane refuses the callHostacceptsJsonhonorsq=0but not relative q-values, and the JSON response sets noVary: AcceptpostMessagethrow rejects with the raw error, not aBackendFunctionError(pre-existing)'*', so its reply is checked against the parent window and request id but not an originDocumentation
packages/core/src/constants.ts(SITES) andpackages/core/src/helpers/site.ts(parseSite)🤖 Generated with Claude Code